#include "login_gw_verify_task.h"

#include <core/QbLogger.h>
#include <core/sharedata/login_data.h>
#include <core/system/guard.h>
#include <core/system/thread_wrapper.h>
#include <qbkernel/include/qb_base.h>
#include <qbprotocol/include/MessageParser.h>
#include <qbprotocol/include/RequestNetWrapper.h>
#include <qbprotocol/include/SSQBModel.h>
#include <qbprotocol/include/rdMessage.h>
#include <qbprotocol/include/ssLoginProto.h>

#include <thread>
#ifndef WIN32
#include <arpa/inet.h>
#endif

#define GateVersion "V8"

namespace qb {
CLoginGwVerifyTask::CLoginGwVerifyTask() {
  memset(&m_HeadAck, 0, sizeof(m_HeadAck));

  m_zip = NULL;
  m_ziplen = 0;
}

CLoginGwVerifyTask::~CLoginGwVerifyTask() {
  if (m_zip) {
    delete[] m_zip;
    m_zip = NULL;
  }
}

void CLoginGwVerifyTask::StartImpl() {
  char buf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN] = {0};
  int32_t buflen = 0;
  makeLoginData(buf, buflen);

  loginData::instance().SetCurrentStatus(eNetStatus_VerifyGW);
  int nRet = qbBase::getMessageKernel()->Send(loginData::instance().ConnectID(),
                                              buf, buflen);
  if (nRet < 0) {
    // 发送错误
    log_error("OnConnectError");

    NotifyFailed(eNetStatus_VerifyGW, eNetError_SendToServerFailed);
    return;
  }
}

void CLoginGwVerifyTask::makeLoginData(char* buf, int& buflen) {
  xMsgHeadReq_t xhead;
  xLoginMktSvrReq_t xBody;
  memset(&xBody, 0x00, sizeof(xBody));

  xhead.msgtype = htonl(E_FID_CS_LOGIN_REQ_V2);
  strcpy(xBody.accountname,
         loginData::instance().UserInfo().strAccount.c_str());
  strcpy(xBody.userID, loginData::instance().UserInfo().strUserID.c_str());
  strcpy(xBody.cookie, loginData::instance().UserInfo().strCookie.c_str());
  strcpy(xBody.mac, loginData::instance().UserInfo().strMac.c_str());

  rdMessage::bPack((char*)&xhead, sizeof(xhead), (char*)&xBody, sizeof(xBody),
                   buf, &buflen);
}

void CLoginGwVerifyTask::TerminateImpl() {}

void CLoginGwVerifyTask::OnNetData(char* pRecvData, int nDataLen) {
  QB_CHECK_RETURN_VOID1(pRecvData && nDataLen > 0);

  xMsgHeadAck_t xHead;
  memcpy(&xHead, pRecvData, sizeof(xHead));
  xHead.msgtype = ntohl(xHead.msgtype);
  xHead.retcode = ntohs(xHead.retcode);
  xHead.idx = ntohs(xHead.idx);
  xHead.num = ntohs(xHead.num);

  if (xHead.msgtype == E_FID_CS_LOGIN_REQ_V2 ||
      xHead.msgtype == E_FID_CS_RE_LOGIN_REQ_V2) {
    if (xHead.retcode == E_RC_OK) {
      xLoginMktSvrAck_t msg;
      memset(&msg, 0, sizeof(msg));
      memcpy(&msg, pRecvData + sizeof(xHead), sizeof(msg));

      msg.encrpyt = ntohl(msg.encrpyt);
      msg.crc = ntohl(msg.crc);
      msg.zip = ntohl(msg.zip);
      rdMessage::SetPack(msg.crc, msg.encrpyt, msg.zip);

      SendClientInfo();

      NotifyLoginStep(eNetStatus_VerifyGW, 0);
      NotifyFinished();
    } else {
      NotifyFailed(eNetStatus_VerifyGW, xHead.retcode);
    }
  }
}

void CLoginGwVerifyTask::SendClientInfo() {
  SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_SEND_CLIENT_INFO;

  QBSendClientInfo_t req;
  QBSendClientInfo_t* ptr = &req;
  memset(ptr, 0, sizeof(QBSendClientInfo_t));
  strcpy(ptr->m_PriceFlag, "V6");
  strcpy(ptr->m_VersionLable, "5.1.1.3");
  strcpy(ptr->m_CompanyID, "10");

  char szIPnPort[32];
  sprintf(szIPnPort, "%s:%d",
          loginData::instance().GetGatewayLoginAddress().strIPAdress.c_str(),
          loginData::instance().GetGatewayLoginAddress().uPort);
  strcpy(ptr->m_ServerIPnPort, szIPnPort);
  Req.m_pRequest = (void*)ptr;

  MessagePoster mp(
      &Req, std::bind(&CLoginGwVerifyTask::WrapReq, this, std::placeholders::_1,
                      std::placeholders::_2));
  int res = mp.send();
}

void CLoginGwVerifyTask::WrapReq(qb::proto::Message& msg, SSRequestMsg* req) {
  switch (req->m_FuncID) {
    case E_FID_QB_SEND_CLIENT_INFO: {
      QBSendClientInfo_t* pdata = (QBSendClientInfo_t*)req->m_pRequest;
      qb::proto::VariantMap submsg;
      submsg.SetString("PriceFlag", pdata->m_PriceFlag);
      submsg.setString("VersionLable", pdata->m_VersionLable);
      submsg.setString("CompanyID", pdata->m_CompanyID);
      submsg.setString("CpuParam", pdata->m_CpuParam);
      submsg.setString("MemSize", pdata->m_MemSize);
      submsg.setString("OSVersion", pdata->m_OSVersion);
      submsg.setString("PowerPlanName", pdata->m_PowerPlanName);
      submsg.setString("TimeSpanScreenShutDown",
                       pdata->m_TimeSpanScreenShutDown);
      submsg.setString("TimeSpanSleep", pdata->m_TimeSpanSleep);
      submsg.setString("ServerIPnPort", pdata->m_ServerIPnPort);
      msg.SetMap("QBSendClientInfo", submsg);
    } break;
    default:
      break;
  }
}

}  // namespace qb
